/*
 * Party.h
 *
 *  Created on: 2013. 9. 26.
 *      Author: jjaehuny
 */

#ifndef PROJECTZ_NLOGIC_PARTY_H_
#define PROJECTZ_NLOGIC_PARTY_H_

#include <map>
#include <vector>
#include <Dispatcher/Timer.h>

namespace ProjectZ {
class User;
} /*ProjectZ*/

namespace ProjectZ { namespace NLogic {

class Space;
class Battle;

class Party : public::Dispatcher::Timer::IObserver
{
public:
	typedef	std::map<int, User *>	USERTREE;
	typedef 	std::vector<User *>		USERVECTOR;

public:
	enum class State {
		__NONE__,

		INVITE,			// OTHER OR FRIEND USER
		ACCEPT_WAIT,
		READY_WAIT,
		DUNGEON_BATTLE,	// 던전에서 전투중..
		DUNGEON_CLEAR,


		PVP_ACCEPT_WAIT,
		PVP_ENTERROOM_WAIT,
		PVP_READY_WAIT,
		PVP_BATTLE,
		PVP_BATTLE_END,

		PK_ACCEPT_WAIT,
		PK_ENTER_WAIT,
		PK_READY_WAIT,
		PK_BATTLE,
		PK_END,
		PK_CANCEL,


		NEW_PARTY_ROOM_WAIT,
		NEW_PK_ROOM_WAIT,
		NEW_PVP_ROOM_ACCEPT_WAIT,

		WORLD_BOSS_WAIT,
		WORLD_BOSS_WAIT_FRIEND,

		HEAL_BUFF,

		__MAX__,
	};

public:
	enum class TimerID {
		__NONE__,

		PK,

		__MAX__,
	};

public:
	Party();
	virtual ~Party();

	void	Initialize();
	void 	Finalize();

	void 	Open(User * pMaster);
	User *	GetMaster();

	bool	EnterUser(User * pUser);
	bool	LeaveUser(User * pUser);

	void	leaveMasterFromDungeon();
	void	leaveUserFromDungeon(User * pUser);

	void	leaveMasterFromPVP();
	void	leaveUserFromPVP(User * pUser);

	void	leaveMasterFromPK();
	void	leaveUserFromPK(User * pUser);

	void	leaveMasterFromNewPartyRoom();
	void	leaveUserFromNewPartyRoom(User * pUser);

	void	leaveMasterFromNewPVPRoom();
	void	leaveUserFromNewPVPRoom(User * pUser);
	
	void	leaveMasterFromWorldBoss();
	void	leaveUserFromWorldBoss(User * pUser);

	User *	FindAllUser(int userseq);

	void	ReadyUserTreeMoveToPlayUserTree();
	// 맵이 클리어된 경우 다시 Ready 를 기다리기 위하여 이 처리를 진행 해야 한다.
	void	PlayUserTreeMoveToAcceptUserTree();

	USERTREE & 	GetAllUserTree();

	int		GetAcceptCount() { return _acceptCount; }
	void	AddAcceptCount() { _acceptCount++; }
	int 	GetRefuseCount() { return _refuseCount; }
	void	AddRefuseCount() { _refuseCount++; }
	int		GetReadyCount() { return _readyCount; }
	void	AddReadyCount() { _readyCount++; }

	void 	SetState(State eState);
	State	GetState() { return _state; }

	bool	AddInviteUserTree(User * pUser);
	bool	AddAcceptUserTree(User * pUser);
	bool	AddReadyUserTree(User * pUser);
	bool	AddPlayUserTree(User * pUser);

	USERTREE & 	GetInviteUserTree() { return _clsInviteUserTree; }
	USERTREE & 	GetAcceptUserTree() { return _clsAcceptUserTree; }
	USERTREE & 	GetReadyUserTree() { return _clsReadyUserTree; }
	USERTREE & 	GetPlayUserTree() { return _playUserTree; }
	USERTREE & 	GetDelayUserTree() { return _pkDelayUserTree; }

	void SetTimer(uint32_t millisec, TimerID id);
	bool OnTime(int id, void* param);

	void 	EndPVPBattle();
	void	EndPKBattle();

	bool	IsPVPDelayUser(User * pUser);
	User *	GetPVPDelayUser() { return _pvpDelayUser; }

	void	SetSpace(Space * pSpace) { _space = pSpace; }
	Space *	GetSpace() { return _space; }

	void	SetRoomWaitEndTime(unsigned int roomWaitEndTime) { _roomWaitEndTime = roomWaitEndTime; }
	unsigned int GetRoomWaitEndTime() { return _roomWaitEndTime; }

	unsigned int GetCreateHpBuffKey() { return _createHpBuffKey; }
	void	ReSetCreateHpBuffKey(unsigned int key) { _createHpBuffKey = key; }

	void	SetHealBuff(User * pUser);

private:
	bool	isMaster(User * pUser);
	bool	leaveMaster();
	bool	leaveUser(User * pUser);

	void 	setTimer(unsigned int interval, int timerID);
	void	killTimer(int timerID);

	bool	onTime_ACCEPT_WAIT();
	bool	onTime_READY_WAIT();
	bool	onTime_DUNGEON_BATTLE();
	void	onTime_DUNGEON_BATTLE_CheckPlayer();
	bool	onTime_DUNGEON_CLEAR();

	bool	onTime_PVP_ACCEPT_WAIT();
	bool	onTime_PVP_ENTERROOM_WAIT();
	bool	onTime_PVP_READY_WAIT();
	bool	onTime_PVP_BATTLE();
	bool	onTime_NEW_PVP_ROOM_WAIT();

	bool	onTime_PK_ACCEPT_WAIT();
	bool	onTime_PK_CANCEL();
	bool	onTime_PK_READY_WAIT();
	bool	onTime_PK_BATTLE();
	bool	onTime_PK_END();

	bool	onTime_New_Party_Room();

	bool	onTime_WORLDBOSS_WAIT();
	bool	onTime_WORLDBOSS_WAIT_FRIEND();

	bool	onTime_HEAL_BUFF();

	void	Start_AI_PK(USERTREE & delayUserTree);
	void	Stop_AI_PK(USERTREE & delayUserTree);
	void	AllStop_AI_PK();

	bool	checkTimeout();

	void	CreateHpBuff();

private:
	User *			_master;
	USERTREE		_clsAllUserTree;		// master 포함한 유저 트리

	USERTREE		_clsInviteUserTree;
	USERTREE		_clsAcceptUserTree;
	USERTREE		_clsReadyUserTree;
	USERTREE		_playUserTree;

	int				_acceptCount;
	int				_refuseCount;
	bool			_startBattle;
	int 			_readyCount;

	State			_state;

	unsigned int	_tick;
	unsigned int	_interval;
	unsigned int	_roomWaitEndTime;

	int				_createHpBuffCoolTimeCount;
	unsigned int	_createHpBuffKey;

	Battle *		_healBuffBattle;

	int				_healBuffTotalTimeCount;

	bool			_isChangeMaster;
	User *			_pvpDelayUser;
	User *			_pkAIPlayUser;
	USERTREE		_pkDelayUserTree;

	USERVECTOR		_clsPKDelayUserVectorOld;
	USERVECTOR		_clsPKDelayUserVectorNew;

	Space *		_space;
};

} /*NLogic*/ } /* namespace ProjectZ */

#endif /* PROJECTZ_NLOGIC_PARTY_H_ */
